<?php
namespace Common\Org\AgentPay;
class AgentPayServices {
	public $timezone = "Asia/Shanghai";
	public $app_id = "1441071499740581"; //该处配置您的APPID
	public $md5_key = "DK96gnOB7EmVDDaHgLTLEZqVgP0H0nML"; //该处配置您的应用秘钥
	public $des_key = "Z5CbXbEaJA6CYRSDS5Ddsab6"; //该处配置您的DES秘钥
	public $trans_url = "http://posp.ipaynow.cn:20320";
	public $query_url = "http://yzpay.codecamp.com/";
	public $check_funcode;

	const VERIFY_HTTPS_CERT = false;
	const QUERY_FUNCODE = "ID01_Query";
	const CHARSET = "UTF-8";
	const QSTRING_EQUAL = "=";
	const QSTRING_SPLIT = "&";
	const SERVER_PARSE_SUCCESS = "1";
	const SERVER_PARSE_FAIL = "0";

	public function __construct($config = array()) {
		foreach ($config as $k => $one) {
			$this->$k = $one;
		}

	}
	public function buildAndSendCheckReq(Array $req) {
		$req_content = $this->buildReqTemplate($this->check_funcode, $req);
		$this->outLog("验证接口请求:", $req_content);
		$resp_content = $this->sendMessage($req_content, $this->trans_url);
		$this->outLog("验证接口验证应答:", $resp_content);
		return Self::parseResp($resp_content);
	}

	public function buildAndSendQueryReq(Array $req) {
		$req_content = $this->buildReqTemplate(Self::QUERY_FUNCODE, $req);
		$this->outLog("查询接口请求:", $req_content);
		$resp_content = $this->sendMessage($req_content, $this->$query_url);
		$this->outLog("查询接口应答:", $resp_content);
		return Self::parseResp($resp_content);
	}

	private function buildReqTemplate($funcode, Array $req_content) {
		$original_text = $this->createLinkString($req_content, true, false);
		$header = "funcode=" . $funcode;
		$message_data_one = base64_encode('appId=' . $this->app_id);
		$message_data_two = base64_encode($this->encrypt($original_text));
		$message_data_three = base64_encode(md5($original_text . $this->md5_key));
		$message = urlencode($message_data_one . '|' . $message_data_two . '|' . $message_data_three);
		return $header . '&message=' . $message;
	}

	private function parseResp($resp_content) {
		$resp = explode("|", $resp_content);
		if ($resp[0] == Self::SERVER_PARSE_SUCCESS) {
			//现在支付服务器解析成功后的处理
			return $this->parseSuccessResp($resp);
		} else {
			//现在支付服务器解析失败后的处理
			return $this->parseErrorResp($resp);
		}
	}

	private function parseSuccessResp(Array $resp) {
		$original_text = trim($this->decrypt(base64_decode($resp[1])));
		$server_sign = base64_decode($resp[2]);
		if ($this->isCheckSignatureSucess($original_text, $server_sign)) {
			//签名验证成功处理
			$this->outLog("验证签名", "验证成功");
			return $original_text;
		} else {
			//签名验证失败处理
			$this->outLog("验证签名", "验证失败");
			return "CHECK_SIGN_FAILS";
		}
	}

	private function parseErrorResp(Array $resp) {
		return base64_decode($resp[1]);
	}

	/**
	 * 判断是否验证签名成功
	 * @param $original_text
	 * @param $server_sign
	 * @return bool
	 */
	private function isCheckSignatureSucess($original_text, $server_sign) {
		$local_sign = md5($original_text . $this->md5_key);
		$this->outLog("本地签名:", $local_sign);
		$this->outLog("服务器签名:", $server_sign);
		if ($local_sign == $server_sign) {

			//验证签名成功
			return true;
		} else {
			//验证签名失败
			return false;
		}
	}

	public function getTime($tag) {
		list($usec, $sec) = explode(" ", microtime());
		$now_time = ((float) $usec + (float) $sec);
		list($usec, $sec) = explode(".", $now_time);
		$date = date($tag, $usec);
		return str_replace('x', $sec, $date);
	}

	/**
	 * Æ´½Ó±¨ÎÄ
	 *
	 * @param Array $para
	 * @param Boolean $sort
	 * @param Boolean $encode
	 * @return string
	 */
	public function createLinkString(Array $para, $sort, $encode) {
		if ($sort) {
			$para = $this->argSort($para);
		}
		$linkString = "";
		foreach ($para as $key => $value) {
			if ($encode) {
				$value = urlencode($value);
			}
			$linkString .= $key . Self::QSTRING_EQUAL . $value . Self::QSTRING_SPLIT;
		}
		$linkString = substr($linkString, 0, count($linkString) - 2);
		return $linkString;
	}

	private function argSort($para) {
		ksort($para);
		reset($para);
		return $para;
	}

	/**
	 * 发送信息
	 *
	 * @param type $req_content 请求字符串
	 * @param type $url 请求地址
	 * @return type 应答消息
	 */
	function sendMessage($req_content, $url) {
		if (is_callable("curl_init")) {
			$curl = curl_init();

			$option = array(
				CURLOPT_POST => 1,
				CURLOPT_POSTFIELDS => $req_content,
				CURLOPT_URL => $url,
				CURLOPT_RETURNTRANSFER => 1,
				CURLOPT_HEADER => 0,
				CURLOPT_SSL_VERIFYPEER => $this->VERIFY_HTTPS_CERT,
				CURLOPT_SSL_VERIFYHOST => $this->VERIFY_HTTPS_CERT,
			);

			curl_setopt_array($curl, $option);
			$resp_data = curl_exec($curl);
			if (curl_errno($curl)) {
				throw new \Exception(curl_error($curl), 0);
			} else {
				$httpStatusCode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
				if (200 !== $httpStatusCode) {
					throw new \Exception($reponse, $httpStatusCode);
				}
			}
			if ($resp_data == FALSE) {
				curl_close($curl);
				echo "通讯失败";
			} else {
				curl_close($curl);
				return $resp_data;
			}
		} else {
			echo "不存在curl模块";
		}
	}

	function outLog($api_n, $content) {
		$time = $this->getTime("Y年m月d日G时i分s秒x毫秒");
		$log_str = "$time   $api_n\n$content\n------------------\n";
		// dump($log_str);
		//$file_n = "Log__" . date("Ymd") . ".txt";
		//$file = fopen("../log/$file_n", "a+");
		//fwrite($file, $log_str);
		//fclose($file);
	}
	public function encrypt($data) {
		$cipher = MCRYPT_3DES;
		$mode = MCRYPT_MODE_ECB;
		return mcrypt_encrypt($cipher, $this->des_key, $data, $mode);
	}

	public function decrypt($data) {
		$cipher = MCRYPT_3DES;
		$mode = MCRYPT_MODE_ECB;
		return mcrypt_decrypt($cipher, $this->des_key, $data, $mode);
	}
}